package com.eastdigit.shiro.filter;

import com.eastdigit.shiro.ChainDefinitionSectionMetaSource;
import com.eastdigit.shiro.ShiroConstants;
import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.StringUtils;
import org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter;
import org.apache.shiro.web.util.WebUtils;

/**
 * 基于URL的权限判断过滤器
 * <p>
 * 我们自动根据URL产生所谓的权限字符串，这一项在Shiro示例中是写在配置文件里面的，默认认为权限不可动态配置
 * <p>
 * URL举例：/user/create.do?***=*** -->权限字符串：/user/create.do
 * 
 */
public class URLPermissionsFilter extends PermissionsAuthorizationFilter {

    @Override
    public boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue)
            throws IOException {
        String[] permissions = buildPermissions(request);
        String permission = permissions[0];
        if (!ChainDefinitionSectionMetaSource.isFiltered(permission)) {// 某些action不需要权限过滤
            return true;
        } else {
            boolean isAccessAllowed = super.isAccessAllowed(request, response, permissions);
            if (isAccessAllowed) {
                Subject subject = SecurityUtils.getSubject();
                if ("true".equals(subject.getSession().getAttribute(ShiroConstants.KICKOUT))) {
                    return false;// 用户再其他地方登录了
                }
            }
            return isAccessAllowed;
        }
    }

    /**
     * 根据请求URL产生权限字符串，这里只产生，而比对的事交给Realm
     * 
     * @param request
     * @return
     */
    protected String[] buildPermissions(ServletRequest request) {
        String[] perms = new String[1];
        HttpServletRequest req = (HttpServletRequest) request;
        perms[0] = req.getServletPath();
        return perms;
    }

    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws IOException {
        Subject subject = getSubject(request, response);
        // If the subject isn't identified, redirect to login URL
        if (subject.getPrincipal() == null) {
            saveRequestAndRedirectToLogin(request, response);
        } else {
            String unauthorizedUrl = getUnauthorizedUrl();
            if (StringUtils.hasText(unauthorizedUrl)) {
                // WebUtils.issueRedirect(request, response, unauthorizedUrl);
                try {
                    RequestDispatcher rd = request.getRequestDispatcher(unauthorizedUrl);
                    rd.forward(request, response);// post请求返回json，get请求返回页面
                } catch (ServletException e) {
                    e.printStackTrace();
                }
            } else {
                WebUtils.toHttp(response).sendError(HttpServletResponse.SC_UNAUTHORIZED);
            }
        }
        return false;
    }
}
